﻿// Decompiled with JetBrains decompiler
// Type: Microsoft.InfoCards.Policy
// Assembly: infocard, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 8E14765A-6610-409A-BA36-099A0642905D
// Assembly location: E:\git\ALLIDA\windll\infocard.exe

using Microsoft.InfoCards.Diagnostics;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.ServiceModel;
using System.Xml;

namespace Microsoft.InfoCards
{
  internal class Policy
  {
    private string m_policyXml = string.Empty;
    private SecurityKeyTypeInternal m_keyType = SecurityKeyTypeInternal.AsymmetricKey;
    private OptionalRstParameters m_optionalRstParams = new OptionalRstParameters();
    private List<string> m_nonWhiteListElements = new List<string>();
    private string[] m_requiredClaimUris;
    private string[] m_optionalClaimUris;
    private uint m_keySize;
    private bool m_keySizeSpecified;
    private bool m_keyTypeSpecified;
    private string m_requestType;
    private MemoryStream m_unprocessedPolicyElements;
    private EndpointAddress m_policyAppliesToEpr;
    private bool m_nonWhiteListElementFound;
    private ProtocolProfile m_protocolProfile;

    private Policy()
    {
    }

    public Policy(string originalPolicyXml, string rstPolicyXml)
    {
      this.m_policyXml = originalPolicyXml;
      this.ParsePolicyXml(rstPolicyXml);
    }

    public static Policy CreateMergedPolicy(
      string originalPolicyXml,
      Policy primary,
      Policy secondary)
    {
      Policy policy = new Policy();
      policy.m_policyXml = originalPolicyXml;
      policy.m_requiredClaimUris = primary.m_requiredClaimUris != null ? primary.m_requiredClaimUris : secondary.m_requiredClaimUris;
      policy.m_optionalClaimUris = primary.m_optionalClaimUris != null ? primary.m_optionalClaimUris : secondary.m_optionalClaimUris;
      policy.m_requestType = !string.IsNullOrEmpty(primary.m_requestType) ? primary.m_requestType : secondary.m_requestType;
      policy.m_unprocessedPolicyElements = primary.m_unprocessedPolicyElements;
      policy.m_policyAppliesToEpr = (EndpointAddress) null != primary.m_policyAppliesToEpr ? primary.m_policyAppliesToEpr : secondary.m_policyAppliesToEpr;
      policy.m_keySize = primary.m_keySizeSpecified ? primary.m_keySize : secondary.m_keySize;
      policy.m_keyType = primary.m_keyTypeSpecified ? primary.m_keyType : secondary.m_keyType;
      policy.m_nonWhiteListElements = new List<string>();
      policy.m_nonWhiteListElementFound = primary.m_nonWhiteListElementFound || secondary.m_nonWhiteListElementFound;
      if (primary.m_nonWhiteListElementFound)
        policy.m_nonWhiteListElements.AddRange((IEnumerable<string>) primary.m_nonWhiteListElements);
      if (secondary.m_nonWhiteListElementFound)
        policy.m_nonWhiteListElements.AddRange((IEnumerable<string>) secondary.m_nonWhiteListElements);
      InfoCardTrace.Assert(null != primary.m_protocolProfile, "Received Null Protocol Profile in the Primary Policy");
      policy.m_protocolProfile = primary.ProtocolVersionProfile;
      policy.m_optionalRstParams = OptionalRstParameters.CreateMergedParameters(primary.OptionalRstParams, secondary.OptionalRstParams);
      return policy;
    }

    public string RequestType
    {
      get
      {
        return this.m_requestType;
      }
    }

    public string PolicyXml
    {
      get
      {
        return this.m_policyXml;
      }
    }

    public OptionalRstParameters OptionalRstParams
    {
      get
      {
        return this.m_optionalRstParams;
      }
    }

    public string[] RequiredClaims
    {
      get
      {
        return this.m_requiredClaimUris;
      }
    }

    public string[] OptionalClaims
    {
      get
      {
        return this.m_optionalClaimUris;
      }
    }

    public SecurityKeyTypeInternal KeyType
    {
      get
      {
        return this.m_keyType;
      }
    }

    public bool KeyTypeSpecified
    {
      get
      {
        return this.m_keyTypeSpecified;
      }
    }

    public EndpointAddress PolicyAppliesTo
    {
      get
      {
        return this.m_policyAppliesToEpr;
      }
    }

    public MemoryStream UnprocessedPolicyElements
    {
      get
      {
        return this.m_unprocessedPolicyElements;
      }
    }

    public bool KeySizeSpecified
    {
      get
      {
        return this.m_keySizeSpecified;
      }
    }

    public uint KeySize
    {
      get
      {
        return this.m_keySize;
      }
    }

    public bool NonWhiteListElementsFound
    {
      get
      {
        return this.m_nonWhiteListElementFound;
      }
    }

    public List<string> NonWhiteListElements
    {
      get
      {
        return this.m_nonWhiteListElements;
      }
    }

    public ProtocolProfile ProtocolVersionProfile
    {
      get
      {
        return this.m_protocolProfile;
      }
    }

    public void ParsePolicyXml(string policyXml)
    {
      XmlReader reader = InfoCardSchemas.CreateReader(policyXml);
      try
      {
        this.m_protocolProfile = new ProtocolProfile(policyXml);
        bool isEmptyElement = reader.IsEmptyElement;
        reader.ReadStartElement();
        if (isEmptyElement)
          return;
        while (reader.IsStartElement())
        {
          if (InfoCardConstants.DoesPolicyElementsToBeProcessedListContain(reader.NamespaceURI, reader.LocalName))
          {
            bool flag = false;
            if (reader.IsStartElement(this.ProtocolVersionProfile.WSTrust.SignatureAlgorithm, this.ProtocolVersionProfile.WSTrust.Namespace))
            {
              this.ReadSignatureAlgorithm(reader);
              flag = true;
            }
            else if (reader.IsStartElement(this.ProtocolVersionProfile.WSTrust.EncryptionAlgorithm, this.ProtocolVersionProfile.WSTrust.Namespace))
            {
              this.ReadEncryptionAlgorithm(reader);
              flag = true;
            }
            else if (reader.IsStartElement(this.ProtocolVersionProfile.WSTrust.CanonicalizationAlgorithm, this.ProtocolVersionProfile.WSTrust.Namespace))
            {
              this.ReadCanonicalizationAlgorithm(reader);
              flag = true;
            }
            else if (reader.IsStartElement(this.ProtocolVersionProfile.WSTrust.SignWith, this.ProtocolVersionProfile.WSTrust.Namespace))
            {
              this.ReadSignWith(reader);
              flag = true;
            }
            else if (reader.IsStartElement(this.ProtocolVersionProfile.WSTrust.ClaimsElement, this.ProtocolVersionProfile.WSTrust.Namespace))
            {
              this.ReadClaims(reader);
              flag = true;
            }
            else if (reader.IsStartElement(this.ProtocolVersionProfile.WSTrust.TokenType, this.ProtocolVersionProfile.WSTrust.Namespace))
            {
              this.ReadTokenType(reader);
              flag = true;
            }
            else if (reader.IsStartElement(this.ProtocolVersionProfile.WSTrust.KeyType, this.ProtocolVersionProfile.WSTrust.Namespace))
            {
              this.ReadKeyType(reader);
              flag = true;
            }
            else if (reader.IsStartElement(this.ProtocolVersionProfile.WSTrust.KeySize, this.ProtocolVersionProfile.WSTrust.Namespace))
            {
              this.ReadKeySize(reader);
              flag = true;
            }
            else if (reader.IsStartElement(this.ProtocolVersionProfile.WSTrust.EncryptWith, this.ProtocolVersionProfile.WSTrust.Namespace))
            {
              this.ReadEncryptWith(reader);
              flag = true;
            }
            else if (reader.IsStartElement(this.ProtocolVersionProfile.WSTrust.RequestType, this.ProtocolVersionProfile.WSTrust.Namespace))
            {
              this.ReadRequestType(reader);
              flag = true;
            }
            else if (XmlNames.WSSpecificationVersion.WSTrustOasis2007 == this.ProtocolVersionProfile.WSTrust.Version && reader.IsStartElement(this.ProtocolVersionProfile.WSTrust.SecondaryParameters, this.ProtocolVersionProfile.WSTrust.Namespace))
              this.ReadSecondaryParameters(reader);
            else if (XmlNames.WSSpecificationVersion.WSTrustOasis2007 == this.ProtocolVersionProfile.WSTrust.Version && reader.IsStartElement(this.ProtocolVersionProfile.WSTrust.KeyWrapAlgorithm, this.ProtocolVersionProfile.WSTrust.Namespace))
            {
              this.ReadKeyWrapAlgorithm(reader);
              flag = true;
            }
            else if (reader.IsStartElement(this.ProtocolVersionProfile.WSPolicy.AppliesTo, this.ProtocolVersionProfile.WSPolicy.Namespace))
            {
              this.ReadAppliesTo(reader);
              flag = true;
            }
            else
              reader.Skip();
            if (flag)
              reader.ReadEndElement();
          }
          else
          {
            if (!InfoCardConstants.DoesLocalTokenFactoryWhiteListContain(reader.NamespaceURI, reader.LocalName))
            {
              this.m_nonWhiteListElementFound = true;
              this.m_nonWhiteListElements.Add(reader.LocalName);
            }
            this.CopyUnprocessedPolicyElements(reader);
          }
        }
        reader.ReadEndElement();
      }
      catch (FormatException ex)
      {
        throw InfoCardTrace.ThrowHelperError((Exception) new PolicyValidationException(SR.GetString("InvalidPolicySpecified"), (Exception) ex));
      }
      catch (XmlException ex)
      {
        throw InfoCardTrace.ThrowHelperError((Exception) new PolicyValidationException(SR.GetString("InvalidPolicySpecified"), (Exception) ex));
      }
      catch (InvalidOperationException ex)
      {
        throw InfoCardTrace.ThrowHelperError((Exception) new PolicyValidationException(SR.GetString("InvalidPolicySpecified"), (Exception) ex));
      }
    }

    private void ReadClaims(XmlReader reader)
    {
      List<string> stringList1 = new List<string>();
      List<string> stringList2 = new List<string>();
      InfoCardTrace.ThrowInvalidArgumentConditional(this.ProtocolVersionProfile.WSTrust.ClaimsElement != reader.LocalName || this.ProtocolVersionProfile.WSTrust.Namespace != reader.NamespaceURI, reader.LocalName);
      if (XmlNodeType.Element != reader.NodeType)
        return;
      if (reader.IsEmptyElement)
        throw InfoCardTrace.ThrowHelperError((Exception) new PolicyValidationException(SR.GetString("NoClaimsFoundInPolicy")));
      if (!reader.IsStartElement(this.ProtocolVersionProfile.WSTrust.ClaimsElement, this.ProtocolVersionProfile.WSTrust.Namespace))
        return;
      if (reader.IsEmptyElement)
      {
        reader.Read();
      }
      else
      {
        reader.Read();
        while (reader.IsStartElement())
        {
          if (reader.IsStartElement("ClaimType", "http://schemas.xmlsoap.org/ws/2005/05/identity"))
          {
            if (XmlNodeType.EndElement != reader.NodeType)
            {
              string attribute1 = reader.GetAttribute("Uri", "http://schemas.xmlsoap.org/ws/2005/05/identity");
              if (string.IsNullOrEmpty(attribute1))
                attribute1 = reader.GetAttribute("Uri");
              if (string.IsNullOrEmpty(attribute1))
                throw InfoCardTrace.ThrowHelperError((Exception) new PolicyValidationException(SR.GetString("ServiceInvalidClaimUri")));
              string attribute2 = reader.GetAttribute("Optional");
              bool flag1 = false;
              if (!string.IsNullOrEmpty(attribute2))
                flag1 = XmlConvert.ToBoolean(attribute2);
              bool flag2 = false;
              bool flag3 = false;
              foreach (string str in stringList1)
              {
                if (str == attribute1)
                {
                  flag3 = true;
                  break;
                }
              }
              foreach (string str in stringList2)
              {
                if (str == attribute1)
                {
                  flag2 = true;
                  flag3 = true;
                  break;
                }
              }
              if (flag1)
              {
                if (!flag3)
                  stringList2.Add(attribute1);
              }
              else if (!flag3)
                stringList1.Add(attribute1);
              else if (flag2)
              {
                stringList2.Remove(attribute1);
                stringList1.Add(attribute1);
              }
              if (reader.IsEmptyElement)
              {
                reader.Read();
              }
              else
              {
                reader.Read();
                reader.ReadEndElement();
              }
            }
            else
              break;
          }
          else
            reader.Skip();
        }
      }
      InfoCardTrace.ThrowInvalidArgumentConditional(XmlNodeType.EndElement != reader.NodeType, reader.NodeType.ToString());
      this.m_requiredClaimUris = stringList1.ToArray();
      this.m_optionalClaimUris = stringList2.ToArray();
    }

    private void ReadTokenType(XmlReader reader)
    {
      InfoCardTrace.ThrowInvalidArgumentConditional(this.ProtocolVersionProfile.WSTrust.TokenType != reader.LocalName || this.ProtocolVersionProfile.WSTrust.Namespace != reader.NamespaceURI, reader.LocalName);
      this.m_optionalRstParams.TokenType = reader.ReadString();
    }

    public void ReadAppliesTo(XmlReader reader)
    {
      InfoCardTrace.ThrowInvalidArgumentConditional(this.ProtocolVersionProfile.WSPolicy.AppliesTo != reader.LocalName || this.ProtocolVersionProfile.WSPolicy.Namespace != reader.NamespaceURI, reader.LocalName);
      if (reader.IsEmptyElement)
        throw InfoCardTrace.ThrowHelperError((Exception) new PolicyValidationException(SR.GetString("InvalidAppliesToInPolicy", (object) SR.GetString("AppliesToMustOnlyHaveEndpointAddress"))));
      reader.Read();
      EndpointAddress endpointAddress = (EndpointAddress) null;
      if (XmlNodeType.EndElement != reader.NodeType)
      {
        try
        {
          endpointAddress = EndpointAddress.ReadFrom(XmlDictionaryReader.CreateDictionaryReader(reader.ReadSubtree()));
          reader.ReadEndElement();
        }
        catch (Exception ex)
        {
          if (InfoCardTrace.IsFatal(ex))
            throw;
          else
            throw InfoCardTrace.ThrowHelperError((Exception) new PolicyValidationException(SR.GetString("InvalidAppliesToInPolicy", (object) SR.GetString("AppliesToMustOnlyHaveEndpointAddress")), ex));
        }
        if (reader.IsStartElement())
          throw InfoCardTrace.ThrowHelperError((Exception) new PolicyValidationException(SR.GetString("InvalidAppliesToInPolicy", (object) SR.GetString("AppliesToMustOnlyHaveEndpointAddress"))));
      }
      this.m_policyAppliesToEpr = endpointAddress;
    }

    private void ReadKeyType(XmlReader reader)
    {
      InfoCardTrace.ThrowInvalidArgumentConditional(this.ProtocolVersionProfile.WSTrust.KeyType != reader.LocalName || this.ProtocolVersionProfile.WSTrust.Namespace != reader.NamespaceURI, reader.LocalName);
      Uri uri = new Uri(reader.ReadString());
      if (this.ProtocolVersionProfile.WSTrust.KeyTypeSymmetric.Equals((object) uri))
        this.m_keyType = SecurityKeyTypeInternal.SymmetricKey;
      else if (this.ProtocolVersionProfile.WSTrust.KeyTypeAsymmetric.Equals((object) uri))
        this.m_keyType = SecurityKeyTypeInternal.AsymmetricKey;
      else if (this.ProtocolVersionProfile.WSTrust.KeyTypeBearer.Equals((object) uri))
        this.m_keyType = SecurityKeyTypeInternal.NoKey;
      else
        throw InfoCardTrace.ThrowHelperError((Exception) new PolicyValidationException(SR.GetString("KeyTypeNotRecognized", (object) uri.ToString())));
      this.m_keyTypeSpecified = true;
    }

    private void ReadKeySize(XmlReader reader)
    {
      InfoCardTrace.ThrowInvalidArgumentConditional(this.ProtocolVersionProfile.WSTrust.KeySize != reader.LocalName || this.ProtocolVersionProfile.WSTrust.Namespace != reader.NamespaceURI, reader.LocalName);
      try
      {
        this.m_keySize = Convert.ToUInt32(reader.ReadString(), (IFormatProvider) CultureInfo.InvariantCulture);
      }
      catch (FormatException ex)
      {
        throw InfoCardTrace.ThrowHelperError((Exception) new PolicyValidationException(SR.GetString("ServiceBadKeySizeInPolicy"), (Exception) ex));
      }
      catch (OverflowException ex)
      {
        throw InfoCardTrace.ThrowHelperError((Exception) new PolicyValidationException(SR.GetString("ServiceBadKeySizeInPolicy"), (Exception) ex));
      }
      this.m_keySizeSpecified = true;
    }

    private void ReadSignatureAlgorithm(XmlReader reader)
    {
      InfoCardTrace.ThrowInvalidArgumentConditional(this.ProtocolVersionProfile.WSTrust.SignatureAlgorithm != reader.LocalName || this.ProtocolVersionProfile.WSTrust.Namespace != reader.NamespaceURI, reader.LocalName);
      this.m_optionalRstParams.SignatureAlgorithm = reader.ReadString();
    }

    private void ReadEncryptionAlgorithm(XmlReader reader)
    {
      InfoCardTrace.ThrowInvalidArgumentConditional(this.ProtocolVersionProfile.WSTrust.EncryptionAlgorithm != reader.LocalName || this.ProtocolVersionProfile.WSTrust.Namespace != reader.NamespaceURI, reader.LocalName);
      this.m_optionalRstParams.EncryptionAlgorithm = reader.ReadString();
    }

    private void ReadCanonicalizationAlgorithm(XmlReader reader)
    {
      InfoCardTrace.ThrowInvalidArgumentConditional(this.ProtocolVersionProfile.WSTrust.CanonicalizationAlgorithm != reader.LocalName || this.ProtocolVersionProfile.WSTrust.Namespace != reader.NamespaceURI, reader.LocalName);
      this.m_optionalRstParams.CanonicalizationAlgorithm = reader.ReadString();
    }

    private void ReadEncryptWith(XmlReader reader)
    {
      InfoCardTrace.ThrowInvalidArgumentConditional(this.ProtocolVersionProfile.WSTrust.EncryptWith != reader.LocalName || this.ProtocolVersionProfile.WSTrust.Namespace != reader.NamespaceURI, reader.LocalName);
      this.m_optionalRstParams.EncryptWith = reader.ReadString();
    }

    private void ReadSignWith(XmlReader reader)
    {
      InfoCardTrace.ThrowInvalidArgumentConditional(this.ProtocolVersionProfile.WSTrust.SignWith != reader.LocalName || this.ProtocolVersionProfile.WSTrust.Namespace != reader.NamespaceURI, reader.LocalName);
      this.m_optionalRstParams.SignWith = reader.ReadString();
    }

    private void ReadRequestType(XmlReader reader)
    {
      InfoCardTrace.ThrowInvalidArgumentConditional(this.ProtocolVersionProfile.WSTrust.RequestType != reader.LocalName || this.ProtocolVersionProfile.WSTrust.Namespace != reader.NamespaceURI, reader.LocalName);
      this.m_requestType = reader.ReadString();
    }

    private void ReadSecondaryParameters(XmlReader reader)
    {
      InfoCardTrace.ThrowInvalidArgumentConditional(this.ProtocolVersionProfile.WSTrust.SecondaryParameters != reader.LocalName || this.ProtocolVersionProfile.WSTrust.Namespace != reader.NamespaceURI, reader.LocalName);
      while (reader.IsStartElement())
        reader.Skip();
    }

    private void ReadKeyWrapAlgorithm(XmlReader reader)
    {
      InfoCardTrace.ThrowInvalidArgumentConditional(this.ProtocolVersionProfile.WSTrust.KeyWrapAlgorithm != reader.LocalName || this.ProtocolVersionProfile.WSTrust.Namespace != reader.NamespaceURI, reader.LocalName);
      this.m_optionalRstParams.KeyWrapAlgorithm = reader.ReadString();
    }

    private void CopyUnprocessedPolicyElements(XmlReader reader)
    {
      if (this.m_unprocessedPolicyElements == null)
        this.m_unprocessedPolicyElements = new MemoryStream();
      XmlWriter xmlWriter = XmlWriter.Create((Stream) this.m_unprocessedPolicyElements, new XmlWriterSettings()
      {
        OmitXmlDeclaration = true
      });
      xmlWriter.WriteNode(reader, true);
      xmlWriter.Flush();
    }
  }
}
